home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 42
/
Amiga Format AFCD42 (Issue 126, Aug 1999).iso
/
-serious-
/
comms
/
other
/
slrn
/
slrn_src
/
src
/
spool.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-05-14
|
34KB
|
1,489 lines
/* Copyright (c) 1998 John E. Davis (davis@space.mit.edu)
*
* This file is part of slrn.
*
* Slrn is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* Slrn is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with Slrn; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/* Local spool support for slrn added by Olly Betts <olly@mantis.co.uk> */
#include "config.h"
#include "slrnfeat.h"
#define DEBUG_SPOOL 0
#define DEBUG_SPOOL_FILENAME "SLRNDEBUG"
#include <stdio.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include <string.h>
#include <errno.h>
#include <ctype.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <slang.h>
#include "jdmacros.h"
#include <time.h>
#include "misc.h"
#include "slrn.h"
#include "slrndir.h"
#ifndef SLRN_SPOOL_ROOT
# define SLRN_SPOOL_ROOT "/var/spool/news" /* a common place for the newsspool */
#endif
#ifndef SLRN_SPOOL_NOV_ROOT
# define SLRN_SPOOL_NOV_ROOT SLRN_SPOOL_ROOT
#endif
#ifndef SLRN_SPOOL_NOV_FILE
# define SLRN_SPOOL_NOV_FILE ".overview"
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <assert.h>
#include <limits.h>
static int spool_put_server_cmd (char *, char *, unsigned int );
static int spool_select_group (char *, int *, int *);
static void spool_close_server (void);
static int spool_has_cmd (char *);
static int spool_initialize_server (void);
static char *spool_read_line (char *, unsigned int );
static int spool_xpat_cmd (char *, int, int, char *);
static int spool_xgtitle_cmd (char *);
static int spool_select_article (int, char *);
static int spool_xhdr_command (char *, int, char *, unsigned int);
static int spool_list_newsgroups (void);
static int spool_list_active (void);
static char *spool_read_xover (char *, unsigned int);
static char *spool_read_xpat (char *, unsigned int);
static int spool_article_num_exists (int);
static Slrn_Server_Obj_Type Spool_Server_Obj;
/* some state that the NNTP server would take care of if we were using one */
static FILE *Spool_fh_local=NULL;
static char *Spool_Group=NULL;
static char *Spool_Group_Name;
static FILE *Spool_fh_nov=NULL; /* we use the overview file lots, so keep it open */
static int Spool_cur_artnum = 0;
/* These are set when the group is selected. */
static int Spool_Max_Artnum = 0;
static int Spool_Min_Artnum = 0;
static int Spool_Doing_XOver; /* if non-zero, reading from ,overview */
static int Spool_Doing_XPat; /* reading xpat */
static int Spool_fhead=0; /* if non-0 we're emulating "HEAD" so stop on blank line */
static int Spool_fFakingActive=0; /* if non-0 we're doing funky stuff with MH folders */
static int spool_fake_active( char *);
static char *spool_fakeactive_read_line(char *, int);
static int Spool_fakeactive_newsgroups=0;
#if DEBUG_SPOOL
# include <stdarg.h>
static void spool_debug (char *fmt, ...)
{
FILE *fp = NULL;
va_list ap;
if (fp == NULL)
{
fp = fopen (DEBUG_SPOOL_FILENAME, "w");
if (fp == NULL)
return;
}
fprintf (fp, "%lu: ", (unsigned long) clock ());
if (fmt == NULL)
{
fputs ("(NULL)", fp);
}
else
{
va_start(ap, fmt);
vfprintf(fp, fmt, ap);
va_end (ap);
}
putc ('\n', fp);
fflush (fp);
}
#endif
/* close any current file (unless it's the overview file) and NULL the FILE* */
static int spool_fclose_local (void)
{
int res = 0;
Spool_fhead=0;
Spool_fFakingActive=0;
if (Spool_fh_local != NULL)
{
if (Spool_fh_local != Spool_fh_nov)
res = fclose(Spool_fh_local);
Spool_fh_local=NULL;
}
return res;
}
static FILE *spool_open_nov_file (void)
{
char *p, *q;
FILE *fp;
/* The spool_dircat function will exit if it fails to malloc. */
p = slrn_spool_dircat (Slrn_Nov_Root, Spool_Group_Name, 1);
q = slrn_spool_dircat (p, Slrn_Nov_File, 0);
fp = fopen (q,"rb");
SLFREE(q);
SLFREE(p);
return fp;
}
static int Spool_XOver_Next;
static int Spool_XOver_Max;
static int Spool_XOver_Min;
static int spool_nntp_xover (int min, int max)
{
int i, ch;
long fp;
#if DEBUG_SPOOL
spool_debug ("spool_nntp_xover(%d,%d)", min, max);
#endif
Spool_Doing_XOver = 0;
spool_fclose_local ();
if (max > Spool_Max_Artnum)
max = Spool_Max_Artnum;
if (min < Spool_Min_Artnum)
min = Spool_Min_Artnum;
if (Spool_Server_Obj.sv_has_xover)
{
Spool_fh_local = Spool_fh_nov;
if (Spool_fh_local == NULL)
return -1;
/* find first record in range in overview file */
/* first look at the current position and see where we are */
/* this is worth trying as slrn will often read a series of ranges */
fp = ftell (Spool_fh_local);
if ((1 != fscanf (Spool_fh_local,"%d", &i))
|| (i > min))
{
/* looks like we're after the start of the range */
/* therefore we'll have to rescan the file from the start */
rewind (Spool_fh_local);
i = -1;
/* this might be improved by doing some binary-chop style searching */
}
else
{
while (((ch = getc(Spool_fh_local)) != '\n')
&& (ch != EOF))
; /* do nothing */
if (ch == EOF)
{
rewind (Spool_fh_local);
i = -1;
}
}
#if DEBUG_SPOOL
spool_debug ("Starting with i=%d",i);
#endif
while (i < min)
{
fp = ftell( Spool_fh_local );
if (1 != fscanf(Spool_fh_local,"%d", &i))
return -1;
while (((ch = getc (Spool_fh_local)) != '\n')
&& (ch != EOF))
; /* do nothing */
}
#ifndef SEEK_SET
# define SEEK_SET 0
#endif
fseek (Spool_fh_local, fp, SEEK_SET); /* reset to start of line */
}
Spool_XOver_Next = Spool_XOver_Min = min;
Spool_XOver_Max = max;
Spool_Doing_XOver = 1;
return OK_XOVER;
}
static char *spool_read_xover (char *the_buf, unsigned int len)
{
char *p;
long pos;
#if DEBUG_SPOOL
spool_debug ("spool_read_xover");
#endif
if (Spool_Doing_XOver == 0)
return NULL;
if (Spool_XOver_Next > Spool_XOver_Max)
{
Spool_Doing_XOver = 0;
return NULL;
}
while (1)
{
unsigned int buflen;
pos = ftell (Spool_fh_nov);
if (NULL == (p = fgets (the_buf, len, Spool_fh_nov)))
{
Spool_Doing_XOver = 0;
return NULL;
}
buflen = strlen (the_buf);
if (buflen && (the_buf[buflen - 1] == '\n'))
the_buf [buflen - 1] = 0;
/* check if we've reached the end of the requested range */
Spool_XOver_Next = atoi (p);
if (Spool_XOver_Next > Spool_XOver_Max)
{
fseek (Spool_fh_nov, pos, SEEK_SET);
Spool_Doing_XOver = 0;
return NULL;
}
if (Slrn_Spool_Check_Up_On_Nov == 0)
break;
/* check that the article file actually exists */
/* if not, this nov entry is defunct, so ignore it */
#if DEBUG_SPOOL
spool_debug ("Nov entry %ld", Spool_XOver_Next);
#endif
if (0 == spool_article_num_exists (Spool_XOver_Next))
{
#if DEBUG_SPOOL
spool_debug (" - OK");
#endif
break;
}
#if DEBUG_SPOOL
spool_debug (" skipped!");
#endif
}
Spool_XOver_Next++;
return p;
}
static int spool_find_artnum_from_msgid (char *msgid)
{
char buf [4096];
char *p;
int n;
#if DEBUG_SPOOL
spool_debug ("spool_find_artnum_from_msgid('%s')", msgid);
#endif
if (Slrn_Server_Obj->sv_has_xover == 0)
{
unsigned int len = strlen (msgid);
for (n = Spool_Min_Artnum; n <= Spool_Max_Artnum; n++)
{
if (-1 == spool_xhdr_command ("Message-Id", n, buf, sizeof (buf)))
continue;
p = slrn_skip_whitespace (buf);
if (0 == strncmp (p, msgid, len))
return n;
}
return -1;
}
if (OK_XOVER != spool_nntp_xover (1, INT_MAX))
return -1;
while (NULL != spool_read_xover (buf, sizeof(bu